<template>
    <el-form ref="loginForm" :model="loginFormData" status-icon :rules="commonRules" label-width="120px"
        class="demo-loginFormData">
        <el-form-item label="用户名" prop="username" class="username-form-item">
            <el-input v-model="loginFormData.username" type="input" autocomplete="off" />
        </el-form-item>
        <el-form-item label="密码" prop="password">
            <el-input v-model="loginFormData.password" type="password" autocomplete="off" />
        </el-form-item>
        <el-form-item label="验证码" prop="captcha" class="captcha">
            <el-input v-model="loginFormData.captcha" maxlength="5" @keydown.enter="submitForm(loginForm)" />
            <span v-html="captcha" @click="getCaptcha" v-loading="loading"></span>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="submitForm(loginForm)">登录</el-button>
        </el-form-item>
    </el-form>
</template>
  
<script setup>
//引入接口
import * as api from "@/api/users.js"
import { reactive, ref, onMounted } from 'vue'
//引入校验函数
import { commonRules, useSubmitForm } from "../../composition/login/validate"
//引入loading加载框
import { ElLoading } from 'element-plus'
//引入路由对象
import { useRouter } from "vue-router";
//引入store
import { useUser } from "@/store/users";

//使用路由对象
let router = useRouter()

//使用store
let userStore = useUser();

//控制Loading的显示和隐藏
let loading = ref(true);

//表单校验成功后回调的方法
let validateSuccess = () => {
    //发起登入请求
    //1.登入请求之前要先校验验证码,将验证码统一转换成小写
    verifyCaptcha(loginFormData.captcha.toLowerCase());
    console.log('校验成功');
}


//表单校验失败后回调的方法
let validateFaild = () => {
    console.log('校验失败');

}




//使用submitForm
let submitForm = useSubmitForm(validateSuccess, validateFaild)
const loginForm = ref()
// 表单数据来源
const loginFormData = reactive({
    username: '',
    password: '',
    captcha: '',
})

//声明一个展示验证码的响应式变量
let captcha = ref()
//获取验证码
let getCaptcha = async () => {
    //一旦发起请求,就要打开Loading动画
    loading.value = true;
    let res = await api.getCaptchaApi();
    //关闭加载动画
    loading.value = false;
    if (res.data.state) captcha.value = res.data.img;
};

//校验验证码
//1.本地的表单校验通过之后
//2.通过接口校验验证码,一定要配置本地代理
//3.声明loadingInstance,用户存储loading动画实例，校验验证码和登录逻辑都可以调用它
let loadingInstance = null;
let verifyCaptcha = async captcha => {
    //发起登入请求的时候就要加载loading加载动画框
    loadingInstance = ElLoading.service({
        text: '正在登入...',
        background: 'rgba(0,0,0,.4)'
    })
    try {
        //表示验证码校验通过
        //发起登入请求
        let res = await api.verifyCaptchaApi(captcha);
        login(loginFormData.username, loginFormData.password);
    } catch (e) {
        //验证码校验失败,需要重新刷新新的验证码
        // console.log(e);
        getCaptcha();
        //关闭loading加载动画框
        loadingInstance.close()
    }
};
//用户名密码登入逻辑
/**
 * @param {String} username 用户名
 * @param {String} password 密码
 */
let login = async (username, password) => {
    //调用登入请求的接口
    try {
        let res = await api.loginApi(username, password);
      
        //存储token,存到sessionStorage中
        sessionStorage.setItem("cxk", res.data.token);
        //存储用户信息
        userStore.$patch({
            userInfo: res.data.userInfo
        });
        //登入成功需要跳转页面,调到主页
        router.push("/");

    } catch (e) {
        //登入失败也要关闭加载动画框
        loadingInstance.close()
        console.log(e)
    }
};


//首次页面加载调用
onMounted(() => {
    getCaptcha();
});
</script>
  

<style lang="scss" scoped>
// 定制组件,修改样式的思路
//1.找到对应组件结构的类名
//2.重新编写样式,覆盖原来的样式

//样式修改不成功的因素和解决方案

//1.确认类名是否正确

//2.确认权重是否足够 !important

//3.是否需要使用深度选择器 xx :deep(选择器) scoped样式,层级嵌套比较深的时候

.captcha {
    display: flex;

    :deep(.el-input) {
        width: 100px;
        border-right: none;

        .el-input__wrapper {
            border-radius: 5px 0 0 5px;
            box-shadow: none;
        }
    }

    span {
        height: 42px;
        background-color: #fff;
        display: inline-block;
        border-left: none;
        border-radius: 0 5px 5px 0;
        width: 60%;
        cursor: pointer;
    }
}

.el-form {
    padding-right: 50px;
    margin-left: -20px;

    :deep(.el-button--primary) {
        height: 40px;
        width: 250px;
        background: linear-gradient(90deg, #1596fb, #002dff);
    }
}

:deep(.el-form-item__label) {
    color: #fff;
    line-height: 40px;
}

:deep(.el-input__inner) {
    height: 40px;
}
</style>